home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / gnu / gnulib / dkbtrace / pbmplus / source / pnm / pnmtops.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-06  |  14.7 KB  |  550 lines

  1. /* pnmtops.c - read a portable anymap and produce a PostScript file
  2. **
  3. ** Copyright (C) 1989 by Jef Poskanzer.
  4. **
  5. ** Permission to use, copy, modify, and distribute this software and its
  6. ** documentation for any purpose and without fee is hereby granted, provided
  7. ** that the above copyright notice appear in all copies and that both that
  8. ** copyright notice and this permission notice appear in supporting
  9. ** documentation.  This software is provided "as is" without express or
  10. ** implied warranty.
  11. */
  12.  
  13. #include "pnm.h"
  14.  
  15. #define MARGIN 0.95
  16.  
  17. static void putinit ARGS(( char* name, int cols, int rows, int padright, int bps, float scale, int dpi, int pagewid, int pagehgt, int format, int turnflag, int turnokflag, int rleflag ));
  18. static void putitem ARGS(( void ));
  19. static void putxelval ARGS(( xelval xv ));
  20. static void putrest ARGS(( void ));
  21. static void rleputbuffer ARGS(( void ));
  22. static void rleputitem ARGS(( void ));
  23. static void rleputxelval ARGS(( xelval xv ));
  24. static void rleflush ARGS(( void ));
  25. static void rleputrest ARGS(( void ));
  26.  
  27. void
  28. main( argc, argv )
  29.     int argc;
  30.     char* argv[];
  31.     {
  32.     FILE* ifp;
  33.     xel* xelrow;
  34.     register xel* xP;
  35.     int argn, turnflag, turnokflag, rleflag;
  36.     int rows, cols, format, bps, padright, row, col;
  37.     xelval maxval, nmaxval;
  38.     float scale, f;
  39.     int dpi, pagewid, pagehgt;
  40.     char name[100];
  41.     char* cp;
  42.     char* usage = "[-scale <x>] [-turn|-noturn] [-rle|-runlength] [-dpi <n>] [-width <n>] [-height <n>] [-rle|-runlength] [pnmfile]";
  43.  
  44.     pnm_init( &argc, argv );
  45.  
  46.     argn = 1;
  47.     scale = 1.0;
  48.     turnflag = 0;
  49.     turnokflag = 1;
  50.     rleflag = 0;
  51.     /* LaserWriter defaults. */
  52.     dpi = 300;
  53.     pagewid = 612;
  54.     pagehgt = 762;
  55.  
  56.     /* Check for flags. */
  57.     while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
  58.     {
  59.     if ( pm_keymatch( argv[argn], "-scale", 2 ) )
  60.         {
  61.         ++argn;
  62.         if ( argn == argc || sscanf( argv[argn], "%f", &scale ) != 1 )
  63.         pm_usage( usage );
  64.         }
  65.     else if ( pm_keymatch( argv[argn], "-turn", 2 ) )
  66.         turnflag = 1;
  67.     else if ( pm_keymatch( argv[argn], "-noturn", 2 ) )
  68.         turnokflag = 0;
  69.     else if ( pm_keymatch( argv[argn], "-rle", 2 ) ||
  70.               pm_keymatch( argv[argn], "-runlength", 2 ) )
  71.         rleflag = 1;
  72.     else if ( pm_keymatch( argv[argn], "-dpi", 2 ) )
  73.         {
  74.         ++argn;
  75.         if ( argn == argc || sscanf( argv[argn], "%d", &dpi ) != 1 )
  76.         pm_usage( usage );
  77.         }
  78.     else if ( pm_keymatch( argv[argn], "-width", 2 ) )
  79.         {
  80.         ++argn;
  81.         if ( argn == argc || sscanf( argv[argn], "%f", &f ) != 1 )
  82.         pm_usage( usage );
  83.         pagewid = f * 72.0;
  84.         }
  85.     else if ( pm_keymatch( argv[argn], "-height", 2 ) )
  86.         {
  87.         ++argn;
  88.         if ( argn == argc || sscanf( argv[argn], "%f", &f ) != 1 )
  89.         pm_usage( usage );
  90.         pagehgt = f * 72.0;
  91.         }
  92.     else
  93.         pm_usage( usage );
  94.     ++argn;
  95.     }
  96.  
  97.     if ( argn < argc )
  98.     {
  99.     ifp = pm_openr( argv[argn] );
  100.     strcpy( name, argv[argn] );
  101.     if ( strcmp( name, "-" ) == 0 )
  102.         strcpy( name, "noname" );
  103.  
  104.     if ( ( cp = index( name, '.' ) ) != 0 )
  105.         *cp = '\0';
  106.     ++argn;
  107.     }
  108.     else
  109.     {
  110.     ifp = stdin;
  111.     strcpy( name, "noname" );
  112.     }
  113.  
  114.     if ( argn != argc )
  115.     pm_usage( usage );
  116.  
  117.     pnm_readpnminit( ifp, &cols, &rows, &maxval, &format );
  118.     xelrow = pnm_allocrow( cols );
  119.  
  120.     /* Figure out bps. */
  121.     bps = pm_maxvaltobits( (int) maxval );
  122.     if ( bps > 2 && bps < 4 )
  123.     bps = 4;
  124.     else if ( bps > 4 && bps < 8 )
  125.     bps = 8;
  126.     else if ( bps > 8 )
  127.     pm_error( "maxval of %d is too large for PostScript", maxval );
  128.     nmaxval = pm_bitstomaxval( bps );
  129.     
  130.     /* Compute padding to round cols * bps up to the nearest multiple of 8. */
  131.     padright = ( ( ( cols * bps + 7 ) / 8 ) * 8 - cols * bps ) / bps;
  132.  
  133.     putinit(
  134.     name, cols, rows, padright, bps, scale, dpi, pagewid, pagehgt, format,
  135.     turnflag, turnokflag, rleflag );
  136.     for ( row = 0; row < rows; ++row )
  137.     {
  138.     pnm_readpnmrow( ifp, xelrow, cols, maxval, format );
  139.     switch ( PNM_FORMAT_TYPE( format ) )
  140.         {
  141.         case PPM_TYPE:
  142.         /* Color. */
  143.         for ( col = 0, xP = xelrow; col < cols; ++col, ++xP )
  144.         if ( maxval != nmaxval )
  145.             PPM_DEPTH( *xP, *xP, maxval, nmaxval );
  146.         /* First red. */
  147.         for ( col = 0, xP = xelrow; col < cols; ++col, ++xP )
  148.         if ( rleflag )
  149.             rleputxelval( PPM_GETR( *xP ) );
  150.         else
  151.             putxelval( PPM_GETR( *xP ) );
  152.         for ( col = 0; col < padright; ++col )
  153.         if ( rleflag )
  154.             rleputxelval( 0 );
  155.         else
  156.             putxelval( 0 );
  157.         if ( rleflag )
  158.         rleflush();
  159.         /* Then green. */
  160.         for ( col = 0, xP = xelrow; col < cols; ++col, ++xP )
  161.         if ( rleflag )
  162.             rleputxelval( PPM_GETG( *xP ) );
  163.         else
  164.             putxelval( PPM_GETG( *xP ) );
  165.         for ( col = 0; col < padright; ++col )
  166.         if ( rleflag )
  167.             rleputxelval( 0 );
  168.         else
  169.             putxelval( 0 );
  170.         if ( rleflag )
  171.         rleflush();
  172.         /* And blue. */
  173.         for ( col = 0, xP = xelrow; col < cols; ++col, ++xP )
  174.         if ( rleflag )
  175.             rleputxelval( PPM_GETB( *xP ) );
  176.         else
  177.             putxelval( PPM_GETB( *xP ) );
  178.         for ( col = 0; col < padright; ++col )
  179.         if ( rleflag )
  180.             rleputxelval( 0 );
  181.         else
  182.             putxelval( 0 );
  183.         if ( rleflag )
  184.         rleflush();
  185.         break;
  186.         default:
  187.         /* Grayscale. */
  188.         for ( col = 0, xP = xelrow; col < cols; ++col, ++xP )
  189.         {
  190.         if ( maxval != nmaxval )
  191.             PNM_ASSIGN1( *xP, (int) PNM_GET1(*xP) * nmaxval / maxval );
  192.         if ( rleflag )
  193.             rleputxelval( PNM_GET1( *xP ) );
  194.         else
  195.             putxelval( PNM_GET1( *xP ) );
  196.         }
  197.         for ( col = 0; col < padright; ++col )
  198.         if ( rleflag )
  199.             rleputxelval( 0 );
  200.         else
  201.             putxelval( 0 );
  202.         if ( rleflag )
  203.         rleflush();
  204.         break;
  205.         }
  206.         }
  207.  
  208.     pm_close( ifp );
  209.  
  210.     if ( rleflag )
  211.     rleputrest();
  212.     else
  213.     putrest();
  214.  
  215.     pm_close (stdout);
  216.  
  217.     exit( 0 );
  218.     }
  219.  
  220. static int bitspersample, item, bitsperitem, bitshift, itemsperline, items;
  221. static int rleitem, rlebitsperitem, rlebitshift;
  222. static int repeat, itembuf[128], count, repeatitem, repeatcount;
  223.  
  224. #if __STDC__
  225. static void
  226. putinit( char* name, int cols, int rows, int padright, int bps, float scale,
  227.      int dpi, int pagewid, int pagehgt, int format, int turnflag,
  228.      int turnokflag, int rleflag )
  229. #else /*__STDC__*/
  230. static void
  231. putinit( name, cols, rows, padright, bps, scale, dpi, pagewid, pagehgt, format,
  232.      turnflag, turnokflag, rleflag )
  233.     char* name;
  234.     int cols, rows, padright, bps;
  235.     float scale;
  236.     int dpi, pagewid, pagehgt, format, turnflag, turnokflag, rleflag;
  237. #endif /*__STDC__*/
  238.     {
  239.     int icols, irows, devpix;
  240.     float pixfac, scols, srows, llx, lly;
  241.  
  242.     /* Turn? */
  243.     icols = cols;
  244.     irows = rows;
  245.     if ( turnflag || ( turnokflag && cols > rows ) )
  246.     {
  247.     turnflag = 1;
  248.     cols = irows;
  249.     rows = icols;
  250.     }
  251.  
  252.     /* Figure out size. */
  253.     devpix = dpi / 72.0 + 0.5;        /* device pixels per unit, approx. */
  254.     pixfac = 72.0 / dpi * devpix;    /* 1, approx. */
  255.     scols = scale * cols * pixfac;
  256.     srows = scale * rows * pixfac;
  257.     if ( scols > pagewid * MARGIN || srows > pagehgt * MARGIN )
  258.     {
  259.     if ( scols > pagewid * MARGIN )
  260.         {
  261.         scale *= pagewid / scols * MARGIN;
  262.         scols = scale * cols * pixfac;
  263.         srows = scale * rows * pixfac;
  264.         }
  265.     if ( srows > pagehgt * MARGIN )
  266.         {
  267.         scale *= pagehgt / srows * MARGIN;
  268.         scols = scale * cols * pixfac;
  269.         srows = scale * rows * pixfac;
  270.         }
  271.     pm_message(
  272.         "warning, image too large for page, rescaling to %g", scale );
  273.     }
  274.     llx = ( pagewid - scols ) / 2;
  275.     lly = ( pagehgt - srows ) / 2;
  276.  
  277.     fprintf (stdout,  "%%!PS-Adobe-2.0 EPSF-2.0\n" );
  278.     fprintf (stdout,  "%%%%Creator: pnmtops\n" );
  279.     fprintf (stdout,  "%%%%Title: %s.ps\n", name );
  280.     fprintf (stdout,  "%%%%Pages: 1\n" );
  281.     fprintf (stdout, 
  282.     "%%%%BoundingBox: %d %d %d %d\n",
  283.     (int) llx, (int) lly,
  284.     (int) ( llx + scols + 0.5 ), (int) ( lly + srows + 0.5 ) );
  285.     fprintf (stdout,  "%%%%EndComments\n" );
  286.     if ( rleflag )
  287.     {
  288.     fprintf (stdout,  "/rlestr1 1 string def\n" );
  289.     fprintf (stdout,  "/readrlestring {\n" );                /* s -- nr */
  290.     fprintf (stdout,  "  /rlestr exch def\n" );            /* - */
  291.     fprintf (stdout,  "  currentfile rlestr1 readhexstring pop\n" );    /* s1 */
  292.     fprintf (stdout,  "  0 get\n" );                    /* c */
  293.     fprintf (stdout,  "  dup 127 le {\n" );                /* c */
  294.     fprintf (stdout,  "    currentfile rlestr 0\n" );            /* c f s 0 */
  295.     fprintf (stdout,  "    4 3 roll\n" );                /* f s 0 c */
  296.     fprintf (stdout,  "    1 add  getinterval\n" );            /* f s */
  297.     fprintf (stdout,  "    readhexstring pop\n" );            /* s */
  298.     fprintf (stdout,  "    length\n" );                /* nr */
  299.     fprintf (stdout,  "  } {\n" );                    /* c */
  300.     fprintf (stdout,  "    256 exch sub dup\n" );            /* n n */
  301.     fprintf (stdout,  "    currentfile rlestr1 readhexstring pop\n" );/* n n s1 */
  302.     fprintf (stdout,  "    0 get\n" );                /* n n c */
  303.     fprintf (stdout,  "    exch 0 exch 1 exch 1 sub {\n" );        /* n c 0 1 n-1*/
  304.     fprintf (stdout,  "      rlestr exch 2 index put\n" );
  305.     fprintf (stdout,  "    } for\n" );                /* n c */
  306.     fprintf (stdout,  "    pop\n" );                    /* nr */
  307.     fprintf (stdout,  "  } ifelse\n" );                /* nr */
  308.     fprintf (stdout,  "} bind def\n" );
  309.     fprintf (stdout,  "/readstring {\n" );                /* s -- s */
  310.         fprintf (stdout,  "  dup length 0 {\n" );                /* s l 0 */
  311.     fprintf (stdout,  "    3 copy exch\n" );                /* s l n s n l*/
  312.     fprintf (stdout,  "    1 index sub\n" );                /* s l n s n r*/
  313.     fprintf (stdout,  "    getinterval\n" );                /* s l n ss */
  314.     fprintf (stdout,  "    readrlestring\n" );            /* s l n nr */
  315.     fprintf (stdout,  "    add\n" );                    /* s l n */
  316.         fprintf (stdout,  "    2 copy le { exit } if\n" );        /* s l n */
  317.         fprintf (stdout,  "  } loop\n" );                    /* s l l */
  318.         fprintf (stdout,  "  pop pop\n" );                /* s */
  319.     fprintf (stdout,  "} bind def\n" );
  320.     }
  321.     else
  322.     {
  323.     fprintf (stdout,  "/readstring {\n" );                /* s -- s */
  324.     fprintf (stdout,  "  currentfile exch readhexstring pop\n" );
  325.     fprintf (stdout,  "} bind def\n" );
  326.     }
  327.     if ( PNM_FORMAT_TYPE( format ) == PPM_TYPE )
  328.     {
  329.     fprintf (stdout,  "/rpicstr %d string def\n", ( icols + padright ) * bps / 8 );
  330.     fprintf (stdout,  "/gpicstr %d string def\n", ( icols + padright ) * bps / 8 );
  331.     fprintf (stdout,  "/bpicstr %d string def\n", ( icols + padright ) * bps / 8 );
  332.     }
  333.     else
  334.     fprintf (stdout,  "/picstr %d string def\n", ( icols + padright ) * bps / 8 );
  335.     fprintf (stdout,  "%%%%EndProlog\n" );
  336.     fprintf (stdout,  "%%%%Page: 1 1\n" );
  337.     fprintf (stdout,  "gsave\n" );
  338.     fprintf (stdout,  "%g %g translate\n", llx, lly );
  339.     fprintf (stdout,  "%g %g scale\n", scols, srows );
  340.     if ( turnflag )
  341.     fprintf (stdout,  "0.5 0.5 translate  90 rotate  -0.5 -0.5 translate\n" );
  342.     fprintf (stdout,  "%d %d %d\n", icols, irows, bps );
  343.     fprintf (stdout,  "[ %d 0 0 -%d 0 %d ]\n", icols, irows, irows );
  344.     if ( PNM_FORMAT_TYPE( format ) == PPM_TYPE )
  345.     {
  346.     fprintf (stdout,  "{ rpicstr readstring }\n" );
  347.     fprintf (stdout,  "{ gpicstr readstring }\n" );
  348.     fprintf (stdout,  "{ bpicstr readstring }\n" );
  349.     fprintf (stdout,  "true 3\n" );
  350.     fprintf (stdout,  "colorimage\n" );
  351.     pm_message( "writing color PostScript..." );
  352.     }
  353.     else
  354.     {
  355.     fprintf (stdout,  "{ picstr readstring }\n" );
  356.     fprintf (stdout,  "image\n" );
  357.     }
  358.  
  359.     bitspersample = bps;
  360.     itemsperline = items = 0;
  361.     if ( rleflag )
  362.     {
  363.     rleitem = 0;
  364.     rlebitsperitem = 0;
  365.     rlebitshift = 8 - bitspersample;
  366.     repeat = 1;
  367.     count = 0;
  368.     }
  369.     else
  370.     {
  371.     item = 0;
  372.     bitsperitem = 0;
  373.     bitshift = 8 - bitspersample;
  374.     }
  375.     }
  376.  
  377. static void
  378. putitem()
  379.     {
  380.     char* hexits = "0123456789abcdef";
  381.  
  382.     if ( itemsperline == 30 )
  383.     {
  384.     putchar( '\n' );
  385.     itemsperline = 0;
  386.     }
  387.     putchar( hexits[item >> 4] );
  388.     putchar( hexits[item & 15] );
  389.     ++itemsperline;
  390.     ++items;
  391.     item = 0;
  392.     bitsperitem = 0;
  393.     bitshift = 8 - bitspersample;
  394.     }
  395.  
  396. #if __STDC__
  397. static void putxelval( xelval xv )
  398. #else /*__STDC__*/
  399. static void
  400. putxelval( xv )
  401.     xelval xv;
  402. #endif /*__STDC__*/
  403.     {
  404.     if ( bitsperitem == 8 )
  405.     putitem();
  406.     item += xv << bitshift;
  407.     bitsperitem += bitspersample;
  408.     bitshift -= bitspersample;
  409.     }
  410.  
  411. static void
  412. putrest()
  413.     {
  414.     if ( bitsperitem > 0 )
  415.     putitem();
  416.     fprintf (stdout,  "\n" );
  417.     fprintf (stdout,  "grestore\n" );
  418.     fprintf (stdout,  "showpage\n" );
  419.     fprintf (stdout,  "%%%%Trailer\n" );
  420.     }
  421.  
  422. static void
  423. rleputbuffer()
  424.     {
  425.     int i;
  426.  
  427.     if ( repeat )
  428.     {
  429.     item = 256 - count;
  430.     putitem();
  431.     item = repeatitem;
  432.     putitem();
  433.     }
  434.     else
  435.     {
  436.     item = count - 1;
  437.     putitem();
  438.     for ( i = 0; i < count; ++i )
  439.         {
  440.         item = itembuf[i];
  441.         putitem();
  442.         }
  443.     }
  444.     repeat = 1;
  445.     count = 0;
  446.     }
  447.  
  448. static void
  449. rleputitem()
  450.     {
  451.     int i;
  452.  
  453.     if ( count == 128 )
  454.     rleputbuffer();
  455.  
  456.     if ( repeat && count == 0 )
  457.     { /* Still initializing a repeat buf. */
  458.     itembuf[count] = repeatitem = rleitem;
  459.     ++count;
  460.     }
  461.     else if ( repeat )
  462.     { /* Repeating - watch for end of run. */
  463.     if ( rleitem == repeatitem )
  464.         { /* Run continues. */
  465.         itembuf[count] = rleitem;
  466.         ++count;
  467.         }
  468.     else
  469.         { /* Run ended - is it long enough to dump? */
  470.         if ( count > 2 )
  471.         { /* Yes, dump a repeat-mode buffer and start a new one. */
  472.         rleputbuffer();
  473.         itembuf[count] = repeatitem = rleitem;
  474.         ++count;
  475.         }
  476.         else
  477.         { /* Not long enough - convert to non-repeat mode. */
  478.         repeat = 0;
  479.         itembuf[count] = repeatitem = rleitem;
  480.         ++count;
  481.         repeatcount = 1;
  482.         }
  483.         }
  484.     }
  485.     else
  486.     { /* Not repeating - watch for a run worth repeating. */
  487.     if ( rleitem == repeatitem )
  488.         { /* Possible run continues. */
  489.         ++repeatcount;
  490.         if ( repeatcount > 3 )
  491.         { /* Long enough - dump non-repeat part and start repeat. */
  492.         count = count - ( repeatcount - 1 );
  493.         rleputbuffer();
  494.         count = repeatcount;
  495.         for ( i = 0; i < count; ++i )
  496.             itembuf[i] = rleitem;
  497.         }
  498.         else
  499.         { /* Not long enough yet - continue as non-repeat buf. */
  500.         itembuf[count] = rleitem;
  501.         ++count;
  502.         }
  503.         }
  504.     else
  505.         { /* Broken run. */
  506.         itembuf[count] = repeatitem = rleitem;
  507.         ++count;
  508.         repeatcount = 1;
  509.         }
  510.     }
  511.  
  512.     rleitem = 0;
  513.     rlebitsperitem = 0;
  514.     rlebitshift = 8 - bitspersample;
  515.     }
  516.  
  517. #if __STDC__
  518. static void rleputxelval( xelval xv )
  519. #else /*__STDC__*/
  520. static void
  521. rleputxelval( xv )
  522.     xelval xv;
  523. #endif /*__STDC__*/
  524.     {
  525.     if ( rlebitsperitem == 8 )
  526.     rleputitem();
  527.     rleitem += xv << rlebitshift;
  528.     rlebitsperitem += bitspersample;
  529.     rlebitshift -= bitspersample;
  530.     }
  531.  
  532. static void
  533. rleflush()
  534.     {
  535.     if ( rlebitsperitem > 0 )
  536.     rleputitem();
  537.     if ( count > 0 )
  538.     rleputbuffer();
  539.     }
  540.  
  541. static void
  542. rleputrest()
  543.     {
  544.     rleflush();
  545.     fprintf (stdout,  "\n" );
  546.     fprintf (stdout,  "grestore\n" );
  547.     fprintf (stdout,  "showpage\n" );
  548.     fprintf (stdout,  "%%%%Trailer\n" );
  549.     }
  550.